package domain;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate3.HibernateCallback;

import util.DAOException;
import util.VersionException;
import domain.factory.POJOFactory;
import domain.itf.IDAOAddress;

public class DAOAddress extends AbstractDAO implements IDAOAddress {

	public DAOAddress() {}


	public Address getById(final Integer id) throws DAOException {
		try {
			return (Address) getHibernateTemplate().execute(new HibernateCallback() {

				public Address doInHibernate(Session session) throws HibernateException, SQLException {
					String requestString = "from Address address where address.id = :id";
					Query request = session.createQuery(requestString);
					request.setInteger("id", id);
					Object address = request.uniqueResult();
					if (address != null && address instanceof Address)
						return (Address) address;
					throw new HibernateException("Impossible to get the Address. getById(" + id + ").");
				}
			});
		} catch (DataAccessException e) {
			throw new DAOException(e.getMessage());
		}
	}

	@SuppressWarnings("unchecked")
	public List<Address> getAllAddress() throws DAOException
	{		
		try {
			return (List<Address>) getHibernateTemplate().execute(new HibernateCallback() {

				public List<Address> doInHibernate(Session session) throws HibernateException, SQLException {
					String requestString = "from Address address";
					Query request = session.createQuery(requestString);
					List<Address> address = request.list();
					if (address != null)
						return address;
					throw new HibernateException("Impossible to get all Address.");
				}
			});
		} catch (DataAccessException e) {
			throw new DAOException(e.getMessage());
		}
	}


	public Address addAddress(String street, String city, String zip, String country) throws DAOException {
		return this.addAddress(POJOFactory.instance.newAddress(street, city, zip, country));
	}


	public Address addAddress(Address address) throws DAOException {
		try {
			Serializable newId = super.getHibernateTemplate().save(address);
			if (newId instanceof Integer)
				address.setId((Integer) newId);
			else // all ids are Integer in our database
				throw new HibernateException("Impossible to get the id of the new Address.");
			return address;
		} catch (DataAccessException e) {
			e.printStackTrace();
			throw new DAOException("Impossible to create the Address. " + e.getMessage());
		}
	}


	public Address updateAddress(int id, long version, String street, String city,
			String zip, String country) throws DAOException, VersionException {
		Address address = POJOFactory.instance.newAddress(street, city, zip, country);
		address.setId(id);
		address.setVersion(version);
		return this.updateAddress(address);
	}


	public Address updateAddress(Address address) throws DAOException, VersionException {

		// versionning verification
		long version = super.getVersionDB(Address.class, address.getId());
		if (version != address.getVersion())
			throw new VersionException();

		try {
			// update the version before save the adress modification
			address.setVersion(address.getVersion() + 1);

			getHibernateTemplate().update(address);
			return address;
		} catch (DataAccessException e) {
			e.printStackTrace();
			throw new DAOException("Impossible to update the address. " + e.getMessage());
		}
	}


	public boolean deleteAddress(int id) throws DAOException {
		try {
			// get the address before remove
			Object addressO = this.getById(id);
			if (addressO != null && addressO instanceof Address) {
				getHibernateTemplate().delete(addressO);
			}
			return true;
		} catch (DataAccessException e) {
			e.printStackTrace();
			throw new DAOException("Impossible to delete the address. " + e.getMessage());
		}
	}
}
